package org.erepublik.company.scanner;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;

import org.cyberneko.html.parsers.DOMParser;
import org.erepublik.company.Battle;
import org.erepublik.company.ECountry;
import org.erepublik.company.utils.WebpageReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class BattleScanner {

	public BattleScanner() {
	}

	public ArrayList<Battle> getActiveBattles() throws SAXException, IOException, JSONException {

		ArrayList<Battle> battleList = new ArrayList<Battle>();
		for (int i = 1; i <= 5; i++) {
			System.out.println("skanuje strone z bitwami nr " + i);
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			Document page = getPageFromTheInternet(i);
			battleList.addAll(getBattlesStarted(page));
		}

		battleList = removeDuplicates(battleList);

		return battleList;
	}

	private ArrayList<Battle> getBattlesStarted(Document page) throws MalformedURLException, IOException, JSONException {

		ArrayList<Node> nodeList = new ArrayList<Node>();
		ArrayList<Node> resistanceList = new ArrayList<Node>();

		getBattleNodes(page, nodeList);
		getResistanceNodes(page, resistanceList);
		ArrayList<Battle> battles = nodesIntoBattles(nodeList);
		ArrayList<Integer> resistances = nodesIntoResistances(resistanceList);
		battles.addAll(resistanceWarsIntoBattle(resistances));

		return battles;
	}

	private ArrayList<Battle> removeDuplicates(ArrayList<Battle> battles) {
		ArrayList<Battle> battleNoDuplicates = new ArrayList<Battle>();
		for (Battle battle : battles) {
			if (!battleNoDuplicates.contains(battle))
				battleNoDuplicates.add(battle);

		}

		return battleNoDuplicates;
	}

	private ArrayList<Battle> resistanceWarsIntoBattle(ArrayList<Integer> resistances) throws MalformedURLException, IOException,
			JSONException {
		ArrayList<Battle> battles = new ArrayList<Battle>();
		for (Integer warId : resistances) {
			System.out.println("pobieram wojna powstancza nr " + warId);
			JSONObject jsonObject = WebpageReader.getJSONFromErepublikApi("http://api.erepublik.com/v2/feeds/wars/" + warId
					+ ".json");
			JSONArray battlesIds = jsonObject.getJSONArray("battles");
			for (int i = 0; i < battlesIds.length(); i++) {
				int battleID = battlesIds.getJSONObject(i).getInt("id");

				System.out.println("pobieram bitwe powstancza nr " + battleID);
				jsonObject = WebpageReader.getJSONFromErepublikApi("http://api.erepublik.com/v2/feeds/battles/" + battleID
						+ ".json");
				ECountry attacker = ECountry.getCountryByName(jsonObject.getJSONObject("attacker").getString("name"));
				ECountry defender = ECountry.getCountryByName(jsonObject.getJSONObject("defender").getString("name"));

				Battle battle = new Battle();
				battle.setId(battleID);
				battle.setWarId(battleID);
				battle.setBattleStartTime(getBattleStartTime(jsonObject));
				battle.setRegion(jsonObject.getJSONObject("region").getString("name"));
				battle.setResistance(true);
				battle.setAttacker(attacker);
				battle.setDefender(defender);
				battle.setAttackersAllies(new ArrayList<ECountry>());
				battle.setDefendersAllies(new ArrayList<ECountry>());
				battles.add(battle);
			}
		}
		System.out.println("bitew powstanczych: " + battles.size());
		return battles;
	}

	private ArrayList<Integer> nodesIntoResistances(ArrayList<Node> nodeList) {

		ArrayList<Integer> battles = new ArrayList<Integer>();
		for (Node node : nodeList) {

			String link = node.getAttributes().getNamedItem("href").getNodeValue();
			String[] linkSplitted = link.split("/");
			int id = Integer.parseInt(linkSplitted[linkSplitted.length - 1]);
			System.out.println("resistance id = " + id);
			battles.add(id);
		}

		return battles;
	}

	private ArrayList<Battle> nodesIntoBattles(ArrayList<Node> nodeList) {
		ArrayList<Battle> battles = new ArrayList<Battle>();
		for (Node node : nodeList) {
			Battle battle = new Battle();

			String link = node.getAttributes().getNamedItem("href").getNodeValue();
			String[] linkSplitted = link.split("/");
			int id = Integer.parseInt(linkSplitted[linkSplitted.length - 1]);

			JSONObject jsonObject = null;
			try {
				System.out.println("pobieram bitwe nr " + id);
				jsonObject = WebpageReader.getJSONFromErepublikApi("http://api.erepublik.com/v2/feeds/battles/" + id
						+ ".json");
				battle.setWarId(jsonObject.getJSONObject("war").getInt("id"));
				battle.setId(id);
				battle.setBattleStartTime(getBattleStartTime(jsonObject));
				battle.setRegion(jsonObject.getJSONObject("region").getString("name"));
				battle.setResistance(false);
				battle.setAttacker(ECountry.getCountryByName(jsonObject.getJSONObject("attacker").getString("name")));
				battle.setDefender(ECountry.getCountryByName(jsonObject.getJSONObject("defender").getString("name")));
				// battle.setHospitals(hospitalService.getHospitalsFromRegion(battle.getRegion()));
				setCountries(battle);

			} catch (Exception e) {
				e.printStackTrace();
				continue;
			}

			battle.setId(id);
			System.out.println("battle id = " + id);
			battles.add(battle);
		}

		return battles;
	}

	private void setCountries(Battle battle) throws MalformedURLException, IOException, JSONException {
		System.out.println("pobieram wojne nr " + battle.getWarId());
		JSONObject jsonObject = WebpageReader.getJSONFromErepublikApi("http://api.erepublik.com/v2/feeds/wars/" + battle.getWarId()
				+ ".json");
		if (jsonObject.getJSONObject("proclaimed_by").getString("name").equals(battle.getAttacker().getName())) {
			battle.setAttackersAllies(getAlliesFromJSON(jsonObject.getJSONObject("proclaimed_by").getJSONArray("allies")));
			battle.setDefendersAllies(getAlliesFromJSON(jsonObject.getJSONObject("proclaimed_to").getJSONArray("allies")));
		} else {
			battle.setDefendersAllies(getAlliesFromJSON(jsonObject.getJSONObject("proclaimed_by").getJSONArray("allies")));
			battle.setAttackersAllies(getAlliesFromJSON(jsonObject.getJSONObject("proclaimed_to").getJSONArray("allies")));
		}
	}

	private ArrayList<ECountry> getAlliesFromJSON(JSONArray jsonArray) throws JSONException {

		ArrayList<ECountry> countries = new ArrayList<ECountry>();
		for (int i = 0; i < jsonArray.length(); i++) {
			ECountry country = ECountry.getCountryByName(jsonArray.getJSONObject(i).getString("name"));
			countries.add(country);
		}

		return countries;
	}

	private long getBattleStartTime(JSONObject jsonBattle) throws JSONException {
		String startedTime = jsonBattle.getJSONObject("progress").getString("started_at");
		String[] splitedDate = startedTime.split("T");
		String[] splitedDate2 = splitedDate[1].split("-");
		String[] splitedDate3 = splitedDate[0].split("-");
		String[] splitedDate4 = splitedDate2[0].split(":");

		int year = Integer.parseInt(splitedDate3[0]);
		int month = Integer.parseInt(splitedDate3[1]);
		int day = Integer.parseInt(splitedDate3[2]);

		int hour = Integer.parseInt(splitedDate4[0]);
		int minute = Integer.parseInt(splitedDate4[1]);

		Date date = new Date(year - 1900, month - 1, day, hour, minute);
		System.out.println(date);

		return date.getTime();
	}

	private void getBattleNodes(Node page, ArrayList<Node> list) {
		Node node = page.getFirstChild();

		while (node != null) {

			// System.out.println(node.getNodeName());
			if (node != null && "IMG".equals(node.getNodeName()) && node.getAttributes().getNamedItem("title") != null
					&& node.getAttributes().getNamedItem("title").getNodeValue().equals("Region under attack")) {

				list.add(node.getParentNode().getNextSibling().getNextSibling().getFirstChild());

			}
			getBattleNodes(node, list);

			node = node.getNextSibling();
		}

	}

	private void getResistanceNodes(Node page, ArrayList<Node> list) {
		Node node = page.getFirstChild();
		while (node != null) {

			// System.out.println(node.getNodeName());
			if (node != null && "IMG".equals(node.getNodeName()) && node.getAttributes().getNamedItem("title") != null
					&& node.getAttributes().getNamedItem("title").getNodeValue().equals("Resistance war started")) {
				list.add(node.getParentNode().getNextSibling().getNextSibling().getFirstChild());

			}
			getResistanceNodes(node, list);

			node = node.getNextSibling();
		}

	}

	public static void main(String[] args) throws JSONException {

		BattleScanner scanner = new BattleScanner();

		try {
			ArrayList<Battle> battles = scanner.getActiveBattles();
			for (Battle battle : battles) {
				System.out.println(battle.getId());
			}

		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private Document getPageFromTheInternet(int i) throws SAXException, IOException {

		System.out.println("odczytuje o bitwach ze strony " + i);
		String url = "http://www.erepublik.com/en/news/military/" + i + "/0";
		DOMParser parser = new DOMParser();
		parser.parse(url);
		Document page = parser.getDocument();
		return page;
	}

}
